home *** CD-ROM | disk | FTP | other *** search
/ Plug-In Power Pack for Netscape Communicator / Plug-In Power Pack for Netscape Communicator.iso / plugins / dataviews / dvtools / demos / surfdemo / surfeqns.c < prev    next >
C/C++ Source or Header  |  1997-07-10  |  13KB  |  453 lines

  1. #ifndef lint
  2. static char SccsId[]= "@(#)surfeqns.c    V1.4    3/19/92";
  3. #endif
  4.  
  5. /*------------------------------------------------------------------
  6. | file name -- surfeqns.c
  7. |
  8. | Functions associated with calculating the data from the formula
  9. | equations.
  10. |
  11. | functions             Description
  12. | ---------             -----------
  13. | InitData        Initializes the global data
  14. | SetDefaults           Sets the default parameters for the equation
  15. | GenerateData          Generates the data from the equation
  16. |-----------------------------------------------------------------*/
  17.  
  18. #include <math.h>
  19. #include "std.h"
  20. #include "dvstd.h"
  21. #include "dvtools.h"
  22. #include "VOstd.h"
  23. #include "surfdata.h"
  24. #include "dvtoolfuns.h"
  25. #include "dvinteract.h"
  26. #include "VPfundecl.h"
  27. #include "surffundecl.h"
  28.  
  29.  
  30. #define SUM_OF            0
  31. #define DIFFERENCE_OF        1
  32. #define LOG_OF            2
  33. #define SQRT_OF            3
  34. #define TIMES_4            4
  35. #define SIN_OF            5
  36. #define EXPONENTIAL_OF        6
  37.  
  38. #define INITIAL_FORMULA        SUM_OF
  39.  
  40. VOID SetThresholds ();
  41.  
  42. /*------------------------------------------------------------------
  43. |
  44. | InitData
  45. |       Initialize the global parameters associated with generating data
  46. |    from the formula equations.
  47. */
  48. void InitData 
  49. V_P_ ((void))
  50. {
  51.   /* Set up the initial plot information */
  52.   Plot.xdivisions = 30;
  53.   Plot.ydivisions = 30;
  54.   Plot.automaticz = YES;
  55.   Plot.inverted = 1.0;
  56.   Plot.context = NO;
  57.   Plot.format = SURFACE;
  58.  
  59.   /* Set up the initial Formula information */
  60.   Formula.text = FormulaMenu[INITIAL_FORMULA];
  61.   Formula.pick = -1;
  62.   Formula.data = NULL;
  63.   SetDefaults (INITIAL_FORMULA, (DV_BOOL) NO);
  64.  
  65.   /* Initialize the text strings for the text input handlers */
  66.   (VOID) S_SPRINTF (TextStr[XDIV_INPUT], "%d", Plot.xdivisions);
  67.   (VOID) S_SPRINTF (TextStr[YDIV_INPUT], "%d", Plot.ydivisions);
  68.  
  69.   /* Set the last datagen information to the current */
  70.   LastGen.pick = Formula.pick;
  71.   LastGen.xmin = Formula.xmin;
  72.   LastGen.xmax = Formula.xmax;
  73.   LastGen.ymin = Formula.ymin;
  74.   LastGen.ymax = Formula.ymax;
  75.   LastGen.xdiv = Plot.xdivisions;
  76.   LastGen.ydiv = Plot.ydivisions;
  77.   LastGen.autoz = Plot.automaticz;
  78.   LastGen.zmin = Formula.zmin;
  79.   LastGen.zmax = Formula.zmax;
  80.   LastGen.invert = Plot.inverted;
  81.  
  82. }
  83.  
  84. /*------------------------------------------------------------------
  85. |
  86. | SetDefaults
  87. |       Initialize the default parameters associated with a particular
  88. |    equations.
  89. */
  90. void 
  91. SetDefaults (pick, draw_text)
  92.      int pick;
  93.      BOOLPARAM draw_text;
  94. {
  95.   FLOAT tempmax;
  96.  
  97.   /* If there hasn't been a change, don't do anything */
  98.   if (pick == Formula.pick)
  99.     return;
  100.  
  101.   /* Set the new index and assign the new default values */
  102.   Formula.pick = pick;
  103.   switch (pick)
  104.     {
  105.     case SUM_OF:
  106.       /*   x^2 + y^2   */
  107.       Formula.xmin = -50.0;
  108.       Formula.xmax = 50.0;
  109.       Formula.ymin = -50.0;
  110.       Formula.ymax = 50.0;
  111.       Formula.zmin = 0.0;
  112.       Formula.zmax = 5000.0;
  113.       break;
  114.  
  115.     case DIFFERENCE_OF:
  116.       /*   x^2 - y^2   */
  117.       Formula.xmin = -25.0;
  118.       Formula.xmax = 25.0;
  119.       Formula.ymin = -25.0;
  120.       Formula.ymax = 25.0;
  121.       Formula.zmin = -625.0;
  122.       Formula.zmax = 625.0;
  123.       break;
  124.  
  125.     case LOG_OF:
  126.       /*  ln(|x| + |y|  */
  127.       Formula.xmin = -2.0;
  128.       Formula.xmax = 2.0;
  129.       Formula.ymin = -2.0;
  130.       Formula.ymax = 2.0;
  131.       Formula.zmin = -1.5;
  132.       Formula.zmax = 1.5;
  133.       break;
  134.  
  135.     case SQRT_OF:
  136.       /*  sqrt(100 - x^2 - y^2)  */
  137.       Formula.xmin = -12.5;
  138.       Formula.xmax = 12.5;
  139.       Formula.ymin = -12.5;
  140.       Formula.ymax = 12.5;
  141.       Formula.zmin = 0.0;
  142.       Formula.zmax = 10.0;
  143.       break;
  144.  
  145.     case TIMES_4:
  146.       /*  4*x^3*y - 4*x*y^3  */
  147.       Formula.xmin = -0.5;
  148.       Formula.xmax = 0.5;
  149.       Formula.ymin = -0.5;
  150.       Formula.ymax = 0.5;
  151.       Formula.zmin = -0.1F;
  152.       Formula.zmax = 0.1F;
  153.       break;
  154.  
  155.     case SIN_OF:
  156.       /*  sin(pi * r) / (pi * r) */
  157.       Formula.xmin = -4.5;
  158.       Formula.xmax = 4.5;
  159.       Formula.ymin = -4.5;
  160.       Formula.ymax = 4.5;
  161.       Formula.zmin = -0.25;
  162.       Formula.zmax = 1.0;
  163.       break;
  164.  
  165.     case EXPONENTIAL_OF:
  166.       /*  (x^2 + 2*y^2) * e^(1-x^2-y^2)  */
  167.       Formula.xmin = -2.5;
  168.       Formula.xmax = 2.5;
  169.       Formula.ymin = -2.5;
  170.       Formula.ymax = 2.5;
  171.       Formula.zmin = 0.0;
  172.       Formula.zmax = 2.0;
  173.       break;
  174.  
  175.     }
  176.  
  177.   if (Plot.inverted == -1.0)
  178.     {
  179.       tempmax = Formula.zmax;
  180.       Formula.zmax = Formula.zmin * -1.0F;
  181.       Formula.zmin = tempmax * -1.0F;
  182.     }
  183.  
  184.   /* Compute the new actual threshold value */
  185.   SetThresholds ();
  186.  
  187.   /* Set up the text variables for the data limit input objects */
  188.   (VOID) S_SPRINTF (TextStr[XMIN_INPUT], "%.6g", Formula.xmin);
  189.   (VOID) S_SPRINTF (TextStr[XMAX_INPUT], "%.6g", Formula.xmax);
  190.   (VOID) S_SPRINTF (TextStr[YMIN_INPUT], "%.6g", Formula.ymin);
  191.   (VOID) S_SPRINTF (TextStr[YMAX_INPUT], "%.6g", Formula.ymax);
  192.   (VOID) S_SPRINTF (TextStr[ZMIN_INPUT], "%.6g", Formula.zmin);
  193.   (VOID) S_SPRINTF (TextStr[ZMAX_INPUT], "%.6g", Formula.zmax);
  194.  
  195.   if (draw_text)
  196.     {
  197.       /* Change the formula text object to display the new formula */
  198.       PrintMessage (FormulaMenu[pick], YES);
  199.  
  200.       /* Redraw each of the user scaled input objects */
  201.       ReDrawTextInputs ();
  202.     }
  203. }
  204.  
  205. #ifndef    M_PI
  206. #define M_PI    3.14159265358979323846
  207. #endif
  208.  
  209. /*------------------------------------------------------------------
  210. |
  211. | GenerateData
  212. |       Generates the data associated with the current equation.
  213. */
  214. void 
  215. GenerateData (firsttime)
  216.      int firsttime;
  217. {
  218.   FLOAT x, y;                   /* Actual x and y values */
  219.   FLOAT tmp;                    /* Temporary for optimizing */
  220.   FLOAT tmp2;                   /* Temporary for optimizing */
  221.   FLOAT minx, miny, maxx, maxy; /* Min and max range values */
  222.   FLOAT deltax, deltay;         /* Used to step through range */
  223.   INT countx, county;           /* Num divisions in each range */
  224.   INT timinginc;                /* For updating timing dial */
  225.   FLOAT result;                 /* Result of the computation */
  226.   FLOAT *dataptr;               /* Pointer to the data area */
  227.   FLOAT mindata, maxdata;       /* Min and max result for this run */
  228.  
  229.   /* Free the old data area and get a new one of the correct size */
  230.   if (Formula.data)
  231.     S_FREE ((ADDRESS) Formula.data);
  232.   Formula.data = (FLOAT *) S_ALLOC ((LONG) (sizeof (FLOAT) *
  233.                                   Plot.xdivisions * Plot.ydivisions));
  234.   /* Tell the graph where to find the data */
  235.   (VOID) TvdPutBuffer (GraphVdp, (ADDRESS) Formula.data);
  236.   /* Set the dimentions of the plot */
  237.   VPvddim (GraphVdp, 1, Plot.ydivisions, Plot.xdivisions);
  238.   /* Set the timing increment to do 100 updates */
  239.   timinginc = (Plot.xdivisions * Plot.ydivisions) / 50;
  240.   if (timinginc == 0)
  241.     timinginc = 1;
  242.  
  243.  
  244.   /* Set the data limits and compute the increment values */
  245.   minx = Formula.xmin;
  246.   maxx = Formula.xmax;
  247.   miny = Formula.ymin;
  248.   maxy = Formula.ymax;
  249.   deltax = (maxx - minx) / (Plot.xdivisions - 1);
  250.   deltay = (maxy - miny) / (Plot.ydivisions - 1);
  251.  
  252.   /* Get the pointer to the beginning of the data area */
  253.   dataptr = Formula.data;
  254.   /* Set dummy min and max values */
  255.   mindata = 1.0e30F;
  256.   maxdata = -1.0e30F;
  257.  
  258.   y = miny;
  259.   for (county = 0; county < Plot.ydivisions; county++)
  260.     {
  261.       x = minx;
  262.       for (countx = 0; countx < Plot.xdivisions; countx++)
  263.         {
  264.           /* For each data point, apply the correct function */
  265.           switch (Formula.pick)
  266.             {
  267.             case SUM_OF:
  268.               result = x * x + y * y;
  269.               break;
  270.             case DIFFERENCE_OF:
  271.               result = (x * x - y * y);
  272.               break;
  273.             case LOG_OF:
  274.               tmp = (FLOAT)(fabs (x) + fabs (y));
  275.               /* Avoid the discontinuity around ln(0) */
  276.               if (tmp != 0)
  277.                   result = (FLOAT)log (tmp);
  278.               else
  279.                 result = Formula.zmin;
  280.               break;
  281.             case SQRT_OF:
  282.               if (100 - x * x - y * y >= 0.0)
  283.                 result = (FLOAT)sqrt (100 - x * x - y * y);
  284.               /* Don't try to take sqrt of a negative */
  285.               else
  286.                 result = 0.0;
  287.               break;
  288.             case TIMES_4:
  289.               result = 4 * x * x * x * y - 4 * x * y * y * y;
  290.               break;
  291.             case SIN_OF:
  292.               tmp = (FLOAT)sqrt (x * x + y * y);
  293.               /* Don't divide by zero */
  294.               if (tmp == 0)
  295.                 result = 1.0;
  296.               else
  297.                 result = (FLOAT)(sin (M_PI * tmp) / (M_PI * tmp));
  298.               break;
  299.             case EXPONENTIAL_OF:
  300.               tmp = x * x;
  301.               tmp2 = y * y;
  302.               result = (tmp + (tmp2 + tmp2)) * (FLOAT)exp (1 - tmp - tmp2);
  303.               break;
  304.             }
  305.           /* Invert this point if necessary */
  306.           result *= Plot.inverted;
  307.  
  308.           /* Keep track of the minimum and maximum values */
  309.           if (result < mindata)
  310.             mindata = result;
  311.           if (result > maxdata)
  312.             maxdata = result;
  313.  
  314.           /* Advance the data pointer */
  315.           *(dataptr)++ = result;
  316.  
  317.           /* Update the "waiting" meter every "timinginc"-th data point */
  318.           TimingValue += 1.0;
  319.           if ((!firsttime) && (!((INT) TimingValue % timinginc)))
  320.             (VOID) TdpDrawNextObject (MainDrawport, TimingObj);
  321.  
  322.           x += deltax;
  323.         }
  324.       y += deltay;
  325.     }
  326.  
  327.   /* If we're auto scaling, set the range to the local min and max */
  328.   if (Plot.automaticz == YES)
  329.     {
  330.       VPvd_drange (GraphVdp, mindata, maxdata);
  331.       Formula.zmin = mindata;
  332.       Formula.zmax = maxdata;
  333.       SetThresholds ();
  334.       (VOID) S_SPRINTF (TextStr[ZMIN_INPUT], "%.6g", Formula.zmin);
  335.       (VOID) S_SPRINTF (TextStr[ZMAX_INPUT], "%.6g", Formula.zmax);
  336.     }
  337.   /* Else, set the range to be the range defined by the user */
  338.   else
  339.     VPvd_drange (GraphVdp, (DOUBLE) Formula.zmin, (DOUBLE) Formula.zmax);
  340. }
  341.  
  342.  
  343. /*------------------------------------------------------------------
  344. |
  345. | NeedToGenData
  346. |     Determines if we need to generate new data.
  347. */
  348. BOOLPARAM NeedToGenData 
  349. V_P_ ((void))
  350. {
  351.   DV_BOOL gen;
  352.  
  353.   gen = NO;
  354.   if (LastGen.pick != Formula.pick)
  355.     gen = YES;
  356.   if (LastGen.xdiv != Plot.xdivisions)
  357.     gen = YES;
  358.   if (LastGen.ydiv != Plot.ydivisions)
  359.     gen = YES;
  360.   if (LastGen.xmin != Formula.xmin)
  361.     gen = YES;
  362.   if (LastGen.xmax != Formula.xmax)
  363.     gen = YES;
  364.   if (LastGen.ymin != Formula.ymin)
  365.     gen = YES;
  366.   if (LastGen.ymax != Formula.ymax)
  367.     gen = YES;
  368.   if (LastGen.autoz != Plot.automaticz)
  369.     gen = YES;
  370.   else if (LastGen.autoz == NO)
  371.     {
  372.       if (LastGen.zmin != Formula.zmin)
  373.         gen = YES;
  374.       if (LastGen.zmax != Formula.zmax)
  375.         gen = YES;
  376.     }
  377.   if (LastGen.invert != Plot.inverted)
  378.     gen = YES;
  379.  
  380.   if (gen == NO)
  381.     return NO;
  382.  
  383.   LastGen.pick = Formula.pick;
  384.   LastGen.xmin = Formula.xmin;
  385.   LastGen.xmax = Formula.xmax;
  386.   LastGen.ymin = Formula.ymin;
  387.   LastGen.ymax = Formula.ymax;
  388.   LastGen.zmin = Formula.zmin;
  389.   LastGen.zmax = Formula.zmax;
  390.   LastGen.xdiv = Plot.xdivisions;
  391.   LastGen.ydiv = Plot.ydivisions;
  392.   LastGen.autoz = Plot.automaticz;
  393.   LastGen.invert = Plot.inverted;
  394.  
  395.   return YES;
  396. }
  397.  
  398.  
  399. /*------------------------------------------------------------------
  400. |
  401. | CheckPlotData
  402. |    Error messages assocated with checking the parameters.
  403. */
  404. BOOLPARAM CheckPlotData 
  405. V_P_ ((void))
  406. {
  407.   if (FormulaMenuActive || ThreshActive)
  408.     return NO;
  409.   if (!AreInputValuesValid ())
  410.     {
  411.       (VOID) S_PRINTF ("\007");
  412.       (VOID) S_FLUSHCHAR;
  413.       PrintMessage ("Invalid Range or no. of Divisions", NO);
  414.       return NO;
  415.     }
  416.   if (Formula.xmax <= Formula.xmin)
  417.     {
  418.       (VOID) S_PRINTF ("\007");
  419.       (VOID) S_FLUSHCHAR;
  420.       PrintMessage ("X Max must be > X Min", NO);
  421.       return NO;
  422.     }
  423.   if (Formula.ymax <= Formula.ymin)
  424.     {
  425.       (VOID) S_PRINTF ("\007");
  426.       (VOID) S_FLUSHCHAR;
  427.       PrintMessage ("Y Max must be > Y Min", NO);
  428.       return NO;
  429.     }
  430.   if (Formula.zmax <= Formula.zmin)
  431.     {
  432.       if (Plot.automaticz == NO)
  433.         {
  434.           (VOID) S_PRINTF ("\007");
  435.           (VOID) S_FLUSHCHAR;
  436.           PrintMessage ("Z Max must be > Z Min", NO);
  437.           return NO;
  438.         }
  439.     }
  440.  
  441.   return YES;
  442. }
  443.  
  444. void SetThresholds 
  445. V_P_ ((void))
  446. {
  447.   INT i;
  448.  
  449.   for (i = 0; i < NUM_THRESHOLDS; i++)
  450.     ThreshValue[i] = Formula.zmin + (ThreshTable[i].upperlimit / (FLOAT) 32768) *
  451.       (Formula.zmax - Formula.zmin);
  452. }
  453.